﻿using open_api_sdk_csharp.com.chinaums.open.api.constants;
using open_api_sdk_csharp.com.chinaums.open.api.internals.utils;
using open_api_sdk_csharp.com.chinaums.open.api.internals.utils.convertors;
using open_api_sdk_csharp.com.chinaums.open.api.internals.utils.http;
using System;
using System.Text;
/**
服务调用入口
**/
namespace open_api_sdk_csharp.com.chinaums.open.api
{
    public class DefaultOpenApiClient<T> : OpenApiclient<T> where T : OpenApiResponse
    {
        /*
        * 开放平台URL
        */
        private string serverUrl;
        public string ServerUrl
        {
            set { serverUrl = value; }
            get { return serverUrl; }
        }
        /**
         * appId
         */
        private string appId;
        public string AppId
        {
            set { appId = value; }
            get { return appId; }
        }
        /**
         * appKey
         */
        private string appKey;
        public string AppKey
        {
            set { appKey = value; }
            get { return appKey; }
        }
        /**
         * 字符集格式
         */
        private string encodeCharSet;
        public string EncodeCharSet
        {
            set { encodeCharSet = value; }
            get { return encodeCharSet; }
        }
        public DefaultOpenApiClient(string serverUrl, string appId, string appKey)
        {
            this.serverUrl = serverUrl;
            this.appId = appId;
            this.appKey = appKey;
        }
        public DefaultOpenApiClient(string serverUrl, string appId, string appKey, string encodeCharSet)
        {
            this.serverUrl = serverUrl;
            this.appId = appId;
            this.appKey = appKey;
            this.encodeCharSet = encodeCharSet;
        }
        public T execute(OpenApiRequest<T> openApiRequest)
        {
            OpenApiParser<T> openApiParser = new ObjectJsonParser<T>();
            return execute_(openApiRequest, openApiParser, null, null);
        }
        public T execute(OpenApiRequest<T> openApiRequest, String token)
        {
            return execute(openApiRequest, token, null);
        }

        public T execute(OpenApiRequest<T> openApiRequest, String token, String encodeCharSet)
        {
            OpenApiParser<T> openApiParser = new ObjectJsonParser<T>();
            return execute_(openApiRequest, openApiParser, token, encodeCharSet);
        }

        public T execute_(OpenApiRequest<T> openApiRequest, OpenApiParser<T> openApiParser,
            string token, string encodeCharSet)
        {
            ConfigBean configBean = new ConfigBean();
            OpenApiContext context = new OpenApiContext();
            T trsp = null;
            string response = "";
            try
            {
                if (string.IsNullOrEmpty(serverUrl)) throw new OpenApiException("通讯地址未设置！");
                if (string.IsNullOrEmpty(appId)) throw new OpenApiException("开发者appId未设置！");
                if (string.IsNullOrEmpty(appKey)) throw new OpenApiException("开发者appKey未设置！");
                //请求检查
                String request = openApiParser.validRequest(openApiRequest);
                context.StartTime = DateTime.Now.ToFileTime();
                context.RequestId = Guid.NewGuid().ToString("N");
                context.OpenServUrl = serverUrl;
                string url = ServerUrl + "" + openApiRequest.apiVersion() + "" + openApiRequest.serviceCode();
                context.ApiServiceUrl = url;
                context.ApiMethodName = openApiRequest.apiMethodName();
                context.Version = openApiRequest.apiVersion();
                context.AppId = appId;
                context.AppKey = appKey;
                context.ConfigBean = configBean;
                context.ServiceCode = openApiRequest.serviceCode();
                if (openApiRequest.needToken())
                {
                    OpenApiCache.getCurrentToken(context);
                    response = HttpTransport.Instance.doPost(context, request);
                }
                else
                {
                    response = HttpTransport.Instance.doPost(configBean.IsProd, url, token, request);
                }
                if (string.IsNullOrEmpty(response)) throw new OpenApiException("服务提供方未返回！");
                if (!string.IsNullOrEmpty(encodeCharSet))
                {
                    byte[] srcBytes = Encoding.GetEncoding(encodeCharSet).GetBytes(response);
                    trsp = openApiParser.parse(Encoding.GetEncoding(encodeCharSet).GetString(srcBytes));
                }
                else
                {
                    trsp = openApiParser.parse(response);
                }
                //token超时异常处理
                string errcode = trsp.errCode;
                int i = 0;
                while (i>0) {
                    if (string.Equals(errcode, Constants.ERR_CODE.AUTHENTICATION_FAILED)) {
                        OpenApiLogger.logInfo("token获取异常，重新获取发送。");
                        OpenApiCache.removeCache(appId);
                        execute_(openApiRequest, openApiParser, token, encodeCharSet);
                        i++;
                    }
                }
            }
            catch (Exception e)
            {
                OpenApiLogger.logError("异常："+e.StackTrace + "{}:\n" + e.Message);
            }
            return trsp;
        }
    }
}
